package com.zlc.common.util.autocode;

import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.sql.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.*;

import static com.zlc.common.util.autocode.FiledValid.skipFileds;

/**
 * 自动生成代码
 * @author zl
 */
public class CodeDOM {
    /**
     * 数据连接相关
     */
    private static final String URL =
            "jdbc:mysql://106.54.54.254:3306/platform?useUnicode=true&characterEncoding=utf8&autoReconnect=true&useSSL=false&serverTimezone=UTC";
    private static final String USERNAME = "root";
    private static final String PASSWORD = "qwe123!@#";
    private static final String DRIVERCLASSNAME = "com.mysql.cj.jdbc.Driver";
    public static final String TABLE_SCHEMA = "platform";
    /**
     *  表明
     */
    private final String tableName;
    /**
     *  包名
     */
    private final String basePackage;
    /**
     *  实际需要创建的文件夹名
     */
    private final String businessPackage;
    /**
     * 需要创建的文件路径
     */
    private final String basePath;
    /**
     * controller上的生成路径
     */
    private final String baseTableHttpPath;

    private static  Map<String,String> autowiredFieldNames = new HashMap<>();

    /**
     * 构造参数，出入表名
     */
    private CodeDOM(String tableName, String businessPackage, String basePackage) {
        this.tableName = tableName.toLowerCase();
        this.basePackage = basePackage;
        this.businessPackage = businessPackage;
        // System.getProperty("user.dir") 获取的是项目所在路径，如果我们是子项目，则需要添加一层路径
        this.basePath = System.getProperty("user.dir") + "\\src\\main\\java\\" + this.basePackage;
        this.baseTableHttpPath = BasePath.getBaseTableHttpPath(this.tableName);
    }

    /**
     * @Description: 自动生成代码
     * @author: zl
     * @date: 2021/8/20
     */
    public static void main(String[] args) {
        BasePath.TableToPath[] tables = BasePath.TableToPath.values();

        for (BasePath.TableToPath table : tables) {
            String msg = new CodeDOM(table.getTableName(), table.getModelPackage(), BasePath.BASE_PATH).create();
            System.out.println(msg);
        }
    }

    /**
     * 创建pojo实体类
     */
    private void createEntity(TableInfo tableInfo) {

        List<TableFieldInfo> tableFieldInfoList = tableInfo.getTableFieldInfoList();

        String path = basePath
                 + "\\" + businessPackage + "\\model\\entity\\" + baseTableHttpPath + ".java";
        File file = FileUtil.createFile(path);
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("package " + basePackage.replaceAll("\\\\", ".")
                 + businessPackage + ".model.entity;\n" + "\n")
                .append("import com.zlc.common.common.entity.BaseEntity;\n");

        stringBuffer.append("\n")
                .append("import lombok.Data;\n")
                .append("import lombok.EqualsAndHashCode;\n")
                .append("import io.swagger.annotations.ApiModelProperty;\n")
                .append("import com.baomidou.mybatisplus.annotation.TableField;\n")
                .append("import com.baomidou.mybatisplus.annotation.TableName;\n")
                .append("import java.io.Serializable;\n");
        if (tableInfo.isContainsBigDecimal()) {
            stringBuffer.append("import java.math.BigDecimal;\n");
        }

        if (tableInfo.isContainsDate()) {
            stringBuffer.append("import java.util.Date;\n");
        }

        stringBuffer.append("\n/**\n * @author  zl\n")
                .append("* @date ").append(new SimpleDateFormat("yyyy-MM-dd").format(new Date())).append("\n")
                .append(" */\n")
                .append("@Data\n")
                .append("@EqualsAndHashCode(callSuper = true)\n")
                .append("@TableName(value = \"").append(tableName).append("\")\n")
                .append("public class ").append(baseTableHttpPath).append(" extends BaseEntity").append(" implements Serializable {\n")
                .append("\tprivate static final long serialVersionUID = 0L;\n");

        // 遍历设置属性
        for (TableFieldInfo tableFieldInfo : tableFieldInfoList) {
            if (skipFileds(tableFieldInfo.getColumnName())) {
                continue;
            }
            stringBuffer
                .append("\t/**\n\t * " + tableFieldInfo.getColumnComment()  + "\n\t */\n\t")
                    .append("@TableField(value=\""+tableFieldInfo.getColumnName()+"\")")
                    .append("\n\tprivate " + StringUtil.typeMapping(tableFieldInfo)
                    + " " + StringUtil.camelCaseName(tableFieldInfo.getColumnName()) + ";\n\n");
        }

//        // 输出get / set方法
//        for (TableFieldInfo tableFieldInfo : tableFieldInfoList) {
//            if (skipFileds(tableFieldInfo.getColumnName())) {
//                continue;
//            }
//            String add = "";
//
//            stringBuffer.append("\t@TableField(value=\"" + tableFieldInfo.getColumnName() + "\",columnDefinition=\""
//                + getDesc(tableFieldInfo) + "\")\n" + add + "\tpublic " + StringUtil.typeMapping(tableFieldInfo) + " get"
//                + StringUtil.captureName(StringUtil.camelCaseName(tableFieldInfo.getColumnName())) + "() {"
//                + "\n\t\treturn this." + StringUtil.camelCaseName(tableFieldInfo.getColumnName()) + ";" + "\n\t}\n\n" +
//
//                "\tpublic void set" + StringUtil.captureName(StringUtil.camelCaseName(tableFieldInfo.getColumnName())) + "("
//                + StringUtil.typeMapping(tableFieldInfo) + " " + StringUtil.camelCaseName(tableFieldInfo.getColumnName())
//                + ") {\n" + "\t\t this." + StringUtil.camelCaseName(tableFieldInfo.getColumnName()) + " = "
//                + StringUtil.camelCaseName(tableFieldInfo.getColumnName()) + ";" + "\n\t}\n\n");
//        }
        stringBuffer.append("}");
        FileUtil.fileWriter(file, stringBuffer);
    }

    /**
     * 创建vo类
     */
    private void createVo(TableInfo tableInfo) {


        String javaName = (basePackage+"\\"+businessPackage+"\\" + "model\\vo\\" + baseTableHttpPath + "Vo").replaceAll("\\\\",".");

        File file = FileUtil.createFile(basePath
                  + "\\" + businessPackage
                + "\\model\\vo\\" + baseTableHttpPath + "Vo.java");
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("package " + basePackage.replaceAll("\\\\", ".")
                   + businessPackage
                + ".model.vo;\n" + "\n")
                .append("import lombok.Data;\n")
                .append("import lombok.EqualsAndHashCode;\n")
                .append("import com.zlc.common.common.entity.BaseEntity;\n")
                .append("import io.swagger.annotations.ApiModel;\n")
                .append("import io.swagger.annotations.ApiModelProperty;\n");

        stringBuffer.append("\n")
                .append("import java.io.Serializable;\n");
        if (tableInfo.isContainsBigDecimal()) {
            stringBuffer.append("import java.math.BigDecimal;\n");
        }

        if (tableInfo.isContainsDate()) {
            stringBuffer.append("import java.util.Date;\n");
        }

        stringBuffer.append("\n/**\n * @author  zl\n")
                .append(" * @date ").append(new SimpleDateFormat("yyyy-MM-dd").format(new Date())).append("\n")
                .append(" */\n")
                .append("@Data\n")
                .append("@EqualsAndHashCode(callSuper = true)\n")
                .append("@ApiModel(description = \"").append(tableInfo.getTableComment()).append("\")\n")
                .append("public class ").append(baseTableHttpPath).append("Vo extends BaseEntity implements Serializable {\n")
                .append("\tprivate static final long serialVersionUID = 0L;\n");


        List<TableFieldInfo> tableFieldInfoList = tableInfo.getTableFieldInfoList();

        // 遍历设置属性
        for (TableFieldInfo tableFieldInfo : tableFieldInfoList) {
            if (skipFileds(tableFieldInfo.getColumnName())) {
                continue;
            }
            // 对字段进行相关校验
            String columnComment = tableFieldInfo.getColumnComment();
            String validFiled = "";


            stringBuffer.append("\t/**\n\t * " + columnComment + "\n\t */\n" + "\t@ApiModelProperty(value=\"" + getDesc(tableFieldInfo)
                + "\")\n" + validFiled + "\tprivate " + StringUtil.typeMapping(tableFieldInfo) + " "
                + StringUtil.camelCaseName(tableFieldInfo.getColumnName()) + ";" + "\n\n");
        }

        // 输出get / set方法
//        for (TableFieldInfo tableFieldInfo : tableFieldInfoList) {
//            if (skipFileds(tableFieldInfo.getColumnName())) {
//                continue;
//            }
//            stringBuffer.append("\tpublic " + StringUtil.typeMapping(tableFieldInfo) + " get"
//                + StringUtil.captureName(StringUtil.camelCaseName(tableFieldInfo.getColumnName())) + "() {"
//                + "\n\t\treturn this." + StringUtil.camelCaseName(tableFieldInfo.getColumnName()) + ";" + "\n\t}\n\n"
//                + "\tpublic void set" + StringUtil.captureName(StringUtil.camelCaseName(tableFieldInfo.getColumnName()))
//                + "(" + StringUtil.typeMapping(tableFieldInfo) + " " + StringUtil.camelCaseName(tableFieldInfo.getColumnName())
//                + ") {\n" + "\t\t this." + StringUtil.camelCaseName(tableFieldInfo.getColumnName()) + " = "
//                + StringUtil.camelCaseName(tableFieldInfo.getColumnName()) + ";" + "\n\t}\n\n");
//        }

        stringBuffer.append("}");
        FileUtil.fileWriter(file, stringBuffer);
    }

    private String getDesc(TableFieldInfo tableFieldInfo) {
        String desc;
        if (isNotEmpty(tableFieldInfo.getColumnComment())) {
            desc = tableFieldInfo.getColumnComment();
        } else {
            desc = tableFieldInfo.getColumnName();
        }
        return desc;
    }

    boolean isNotEmpty(String content) {
        return content != null && content.trim().length() > 0;
    }

    /**
     * 创建repository类
     */
    private void createRepository(TableInfo tableInfo) {

        String path  = basePath + "\\" + businessPackage
                + "\\mapper\\" + baseTableHttpPath + "Mapper.java";

        File repoFile = new File(path);
        if (repoFile.exists()) {
            return;
        }

        File file = FileUtil.createFile(path);
        StringBuffer stringBuffer = new StringBuffer();
        String t = "String";
        // 遍历属性
        for (TableFieldInfo tableFieldInfo : tableInfo.getTableFieldInfoList()) {
            // 主键
            if ("PRI".equals(tableFieldInfo.getColumnKey())) {
                t = StringUtil.typeMapping(tableFieldInfo);
            }
        }
        stringBuffer.append("package " + basePackage.replaceAll("\\\\", ".")
                + businessPackage
                + ".mapper;\n" + "\n"
                + "import org.apache.ibatis.annotations.Mapper;\n"
                + "import com.baomidou.mybatisplus.core.mapper.BaseMapper;\n"
            + "import " + basePackage.replaceAll("\\\\", ".")  + businessPackage + ".model.entity." + baseTableHttpPath + ";\n"
            + "\n" + "/**\n" + " * @author  zl\n"
            + " * @date " + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + " \n" + " */\n" + "@Mapper\n"
            + "public interface " + baseTableHttpPath + "Mapper extends BaseMapper<" + baseTableHttpPath
            + "> {");
        stringBuffer.append("\n");
        stringBuffer.append("}");
        FileUtil.fileWriter(file, stringBuffer);
    }

    /**
     * 创建service类
     */
    private void createService(TableInfo tableInfo) {

        String path = basePath +  "\\" + businessPackage +
        "\\service\\" + baseTableHttpPath + "Service.java";
        File repoFile = new File(path);
        if (repoFile.exists()) {
            return;
        }
        File file = FileUtil.createFile(path);
        StringBuffer stringBuffer = new StringBuffer();
        String t = "String";
        // 遍历属性
        for (TableFieldInfo tableFieldInfo : tableInfo.getTableFieldInfoList()) {
            // 主键
            if ("PRI".equals(tableFieldInfo.getColumnKey())) {
                t = StringUtil.typeMapping(tableFieldInfo);
            }
        }

        stringBuffer.append("package " + basePackage.replaceAll("\\\\", ".")
                + businessPackage
                + ".service;\n" + "\n"
                + "import com.zlc.common.common.service.BaseService;\n"
            + "import " + basePackage.replaceAll("\\\\", ".")  + businessPackage + ".model.entity." + baseTableHttpPath + ";\n"
                + "import "+basePackage.replaceAll("\\\\", ".")  + businessPackage  + ".model.vo." + baseTableHttpPath + "Vo;\n"
                + "import "+basePackage.replaceAll("\\\\", ".")  + businessPackage  + ".mapper." + baseTableHttpPath + "Mapper;\n"
                + "\n" + "/**\n"
            + " * @author  zl\n" + " * @date " + new SimpleDateFormat("yyyy-MM-dd").format(new Date())
                + " \n"
            + " */\n" + "public interface " + baseTableHttpPath + "Service extends BaseService<" + baseTableHttpPath
            + "Mapper, " + baseTableHttpPath + ", " + baseTableHttpPath + "Vo> {");
        stringBuffer.append("\n");


        stringBuffer.append("}");
        FileUtil.fileWriter(file, stringBuffer);

        // Impl
        String implPath = basePath  +
                 "\\" + businessPackage + "\\service\\impl\\" + baseTableHttpPath + "ServiceImpl.java";
        File file1 = FileUtil.createFile(implPath);

        StringBuffer stringBuffer1 = new StringBuffer();
        stringBuffer1.append("package " + basePackage.replaceAll("\\\\", ".")
                 + businessPackage
                + ".service.impl;\n" + "\n"
                + "import com.zlc.common.common.service.BaseServiceImpl;\n"
            + "import " + basePackage.replaceAll("\\\\", ".")
                  + businessPackage
                + ".model.entity." + baseTableHttpPath + ";\n"
            + "import " + basePackage.replaceAll("\\\\", ".")
                 + businessPackage
                + ".mapper." + baseTableHttpPath + "Mapper;\n"
            + "import " + basePackage.replaceAll("\\\\", ".")
                 + businessPackage
                + ".model.vo." + baseTableHttpPath + "Vo;\n"
            + "import "+ basePackage.replaceAll("\\\\", ".")
                  + businessPackage +
                ".service." + baseTableHttpPath + "Service;\n"
                + "import org.springframework.stereotype.Service;\n"
            + "import org.springframework.transaction.annotation.Transactional;\n" + "\n" + "/**\n"
            + " * @author  zl\n" + " * @date " + new SimpleDateFormat("yyyy-MM-dd").format(new Date()) + " \n"
            + " */\n" + "@Service\n" + "@Transactional(rollbackFor = Exception.class)\n" + "public class " + baseTableHttpPath
            + "ServiceImpl extends BaseServiceImpl<" + baseTableHttpPath + "Mapper, " + baseTableHttpPath + ", " + baseTableHttpPath + "Vo"
            + "> implements " + baseTableHttpPath + "Service{");
        stringBuffer1.append("\n\n");

        stringBuffer1.append("}");
        FileUtil.fileWriter(file1, stringBuffer1);
    }


    /**
     * 获取表结构信息
     * @return
     */
    private TableInfo getTableInfo() {
        Connection conn = null;
        PreparedStatement ps = null;
        ResultSet rs = null;
        TableInfo tableInfo = new TableInfo();
        ArrayList<TableFieldInfo> list = new ArrayList<>(16);

        try {
            conn = DBConnectionUtil.getConnection();

            String tableCommentSql = "select table_name,table_comment from information_schema.tables where table_schema = ? and table_name = ?";
            ps = conn.prepareStatement(tableCommentSql);
            ps.setString(1, TABLE_SCHEMA);
            ps.setString(2, tableName);
            rs = ps.executeQuery();
            while (rs.next()) {
                String tableComment = rs.getString("table_comment");
                tableInfo.setTableComment(tableComment);
            }


            String sql = "select column_name,data_type,column_comment,column_key,extra,is_nullable,"
                + "character_maximum_length from information_schema.columns where table_name=? order by ordinal_position";
            ps = conn.prepareStatement(sql);
            ps.setString(1, tableName);
            rs = ps.executeQuery();
            while (rs.next()) {
                TableFieldInfo tableFieldInfo = new TableFieldInfo();
                // 列名，全部转为小写
                tableFieldInfo.setColumnName(rs.getString("column_name").toLowerCase());
                // 列类型
                String dataType = rs.getString("data_type");
                tableFieldInfo.setDataType(dataType);
                // 列注释
                tableFieldInfo.setColumnComment(rs.getString("column_comment"));
                // 主键
                tableFieldInfo.setColumnKey(rs.getString("column_key"));
                // 主键类型
                tableFieldInfo.setExtra(rs.getString("extra"));
                // 是否为空
                tableFieldInfo.setIsNullAble(rs.getString("is_nullable"));
                // 限制长度
                tableFieldInfo.setLength(rs.getString("character_maximum_length"));

                String typeMapping = StringUtil.typeMapping(tableFieldInfo);
                String columnName = tableFieldInfo.getColumnName();
                if (StringUtils.isNotBlank(columnName)
                        && !("create_time_".equals(columnName) || "update_time_".equals(columnName)
                        || "delete_flag_".equals(columnName))
                ) {
                    switch (typeMapping) {
                        case "BigDecimal":
                            tableInfo.setContainsBigDecimal(Boolean.TRUE);
                            break;
                        case "Date":
                            tableInfo.setContainsDate(Boolean.TRUE);
                            break;
                        default:
                            break;
                    }
                }
                list.add(tableFieldInfo);
            }
            tableInfo.setTableFieldInfoList(list);
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            assert rs != null;
            DBConnectionUtil.close(conn, ps, rs);
        }
        return tableInfo;
    }

    /**
     * 快速创建，供外部调用，调用之前先设置一下项目的基础路径
     */
    private String create() {
        TableInfo tableInfo = getTableInfo();
        createEntity(tableInfo);
        createVo(tableInfo);
        createRepository(tableInfo);
        createService(tableInfo);
        System.out.println("生成路径位置：" + basePath);
        return tableName + " 后台代码生成完毕！";
    }


    private String lowFirstWord(String className) {
        String firstWord = className.substring(0, 1);
        return firstWord.toLowerCase() + className.substring(1);
    }


    /**
     * 字符串处理工具类
     */
    public static class StringUtil {
        /**
         * 数据库类型->JAVA类型
         *
         * @return JAVA类型
         */
        public static String typeMapping(TableFieldInfo tableFieldInfo) {
            String columnName = tableFieldInfo.getColumnName();
            String javaType = "";
            if (columnName.contains("_flag") || columnName.equalsIgnoreCase("flag_")) {
                javaType = "Boolean";
            } else {
                String dbType = tableFieldInfo.getDataType();
                if ("int|integer".contains(dbType)) {
                    javaType = "Integer";
                } else if ("float|double|real|bigint".contains(dbType)) {
                    javaType = "Long";
                } else if ("decimal".contains(dbType)) {
                    javaType = "BigDecimal";
                }else if ("datetime".contains(dbType)) {
                    javaType = "Date";
                } else if ("date|time|timestamp".contains(dbType)) {
                    javaType = "Date";
                } else {
                    javaType = "String";
                }
            }

            return javaType;
        }

        /**
         * 驼峰转换为下划线
         */
        public static String underscommonName(String camelCaseName) {
            StringBuilder result = new StringBuilder();
            if (camelCaseName != null && camelCaseName.length() > 0) {
                result.append(camelCaseName.substring(0, 1).toLowerCase());
                for (int i = 1; i < camelCaseName.length(); i++) {
                    char ch = camelCaseName.charAt(i);
                    if (Character.isUpperCase(ch)) {
                        result.append("_");
                        result.append(Character.toLowerCase(ch));
                    } else {
                        result.append(ch);
                    }
                }
            }
            return result.toString();
        }

        /**
         * 首字母大写
         */
        public static String captureName(String name) {
            char[] cs = name.toCharArray();
            cs[0] -= 32;
            return String.valueOf(cs);

        }

        /**
         * 下划线转换为驼峰
         */
        public static String camelCaseName(String underscommonName) {
            StringBuilder result = new StringBuilder();
            if (underscommonName != null && underscommonName.length() > 0) {
                boolean flag = false;
                for (int i = 0; i < underscommonName.length(); i++) {
                    char ch = underscommonName.charAt(i);
                    if ("_".charAt(0) == ch) {
                        flag = true;
                    } else {
                        if (flag) {
                            result.append(Character.toUpperCase(ch));
                            flag = false;
                        } else {
                            result.append(ch);
                        }
                    }
                }
            }
            return result.toString();
        }
    }

    /**
     * JDBC连接数据库工具类
     */
    private static class DBConnectionUtil {

        {
            // 1、加载驱动
            try {
                Class.forName(DRIVERCLASSNAME);
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }

        /**
         * 返回一个Connection连接
         *
         * @return
         */
        public static Connection getConnection() {
            Connection conn = null;
            // 2、连接数据库
            try {
                conn = DriverManager.getConnection(URL, USERNAME, PASSWORD);
            } catch (SQLException e) {
                e.printStackTrace();
            }
            return conn;
        }

        /**
         * 关闭Connection，Statement连接
         *
         * @param conn
         * @param stmt
         */
        public static void close(Connection conn, Statement stmt) {
            try {
                conn.close();
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

        /**
         * 关闭Connection，Statement，ResultSet连接
         *
         * @param conn
         * @param stmt
         * @param rs
         */
        public static void close(Connection conn, Statement stmt, ResultSet rs) {
            try {
                close(conn, stmt);
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }

    }

    public static class TableInfo {
        private String tableComment;
        private boolean containsDate;
        private boolean containsBigDecimal;
        private List<TableFieldInfo> tableFieldInfoList;

        public String getTableComment() {
            return tableComment;
        }

        public void setTableComment(String tableComment) {
            this.tableComment = tableComment;
        }


        public boolean isContainsDate() {
            return containsDate;
        }

        public void setContainsDate(boolean containsDate) {
            this.containsDate = containsDate;
        }

        public boolean isContainsBigDecimal() {
            return containsBigDecimal;
        }

        public void setContainsBigDecimal(boolean containsBigDecimal) {
            this.containsBigDecimal = containsBigDecimal;
        }

        public List<TableFieldInfo> getTableFieldInfoList() {
            return tableFieldInfoList;
        }

        public void setTableFieldInfoList(List<TableFieldInfo> tableFieldInfoList) {
            this.tableFieldInfoList = tableFieldInfoList;
        }
    }
    /**
     * 表结构行信息实体类
     */
    public static class TableFieldInfo {
        private String columnName;
        private String dataType;
        private String columnComment;
        private String columnKey;
        private String extra;
        private String isNullAble;
        private String length;

        TableFieldInfo() {}

        String getIsNullAble() {
            return isNullAble;
        }

        void setIsNullAble(String isNullAble) {
            this.isNullAble = isNullAble;
        }

        String getLength() {
            return length;
        }

        void setLength(String length) {
            this.length = length;
        }

        String getColumnName() {
            return columnName;
        }

        void setColumnName(String columnName) {
            this.columnName = columnName;
        }

        String getDataType() {
            return dataType;
        }

        void setDataType(String dataType) {
            this.dataType = dataType;
        }

        String getColumnComment() {
            return columnComment;
        }

        void setColumnComment(String columnComment) {
            this.columnComment = columnComment;
        }

        String getColumnKey() {
            return columnKey;
        }

        void setColumnKey(String columnKey) {
            this.columnKey = columnKey;
        }

        String getExtra() {
            return extra;
        }

        void setExtra(String extra) {
            this.extra = extra;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return  true;
            }
            if (o == null || getClass() != o.getClass()) {
                return  false;
            }
            TableFieldInfo tableFieldInfo = (TableFieldInfo)o;
            return Objects.equals(columnName, tableFieldInfo.columnName) && Objects.equals(dataType, tableFieldInfo.dataType)
                && Objects.equals(columnComment, tableFieldInfo.columnComment)
                && Objects.equals(columnKey, tableFieldInfo.columnKey) && Objects.equals(extra, tableFieldInfo.extra)
                && Objects.equals(isNullAble, tableFieldInfo.isNullAble) && Objects.equals(length, tableFieldInfo.length);
        }

        @Override
        public int hashCode() {
            return Objects.hash(columnName, dataType, columnComment, columnKey, extra, isNullAble, length);
        }
    }

    /**
     * file工具类
     */
    private static class FileUtil {
        /**
         * 创建文件
         *
         * @param pathNameAndFileName
         *            路径跟文件名
         * @return File对象
         */
        private static File createFile(String pathNameAndFileName) {
            File file = new File(pathNameAndFileName);
            try {
                // 获取父目录
                File fileParent = file.getParentFile();
                if (!fileParent.exists()) {
                    fileParent.mkdirs();
                }
                // 创建文件
                if (!file.exists()) {
                    file.createNewFile();
                }
            } catch (Exception e) {
                file = null;
                System.err.println("新建文件操作出错");
                e.printStackTrace();
            }
            return file;
        }

        /**
         * 字符流写入文件
         *
         * @param file
         *            file对象
         * @param stringBuffer
         *            要写入的数据
         */
        private static void fileWriter(File file, StringBuffer stringBuffer) {
            // 字符流
            try {
                FileWriter resultFile = new FileWriter(file, false);// true,则追加写入 false,则覆盖写入
                PrintWriter myFile = new PrintWriter(resultFile);
                // 写入
                myFile.println(stringBuffer.toString());

                myFile.close();
                resultFile.close();
            } catch (Exception e) {
                System.err.println("写入操作出错");
                e.printStackTrace();
            }
        }

    }
}
